﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Web;
using System.IO;

namespace MyPublisher.Emit.Social
{
    public class DouBanEmit : IEmit
    {
        private string APIKEY = "0714b4155ed0f949153e1c401c72ebdb";
        private string APIKEY_SECRET = "9197f1ceec7005c5";
        private const string REQUEST_TOKEN = "a6f3ff5367dbed41f4dbfdfa3793c7c3";
        private const string REQUEST_TOKEN_KEY = "8afff29ab6c8738a";
        //oauth_token_secret=b057f2b4e463b5e6&oauth_token=fb945949ad773856f2bd0bdd0865a902&douban_user_id=1082310
        private const string ACCESS_TOKEN = "fb945949ad773856f2bd0bdd0865a902";
        private const string ACCESS_TOKEN_SECRET = "b057f2b4e463b5e6";

        private static readonly Uri REQUEST_TOKEN_URL = new Uri("http://www.douban.com/service/auth/request_token");
        private static readonly Uri ACCESS_TOKEN_URL = new Uri("http://www.douban.com/service/auth/access_token");
        private static readonly string AUTHORIZATION_URL = "http://www.douban.com/service/auth/authorize?oauth_token=";
        private static readonly Uri RECOMMENDATON_Uri = new Uri("http://api.douban.com/recommendations");

        private string requestToken = REQUEST_TOKEN;
        private string requestTokenSecret = REQUEST_TOKEN_KEY;
        private string accessToken = ACCESS_TOKEN;
        private string accessTokenSecret = ACCESS_TOKEN_SECRET;

        private OAuthBase oAuth = new OAuthBase();

        public DouBanEmit()
        {
            //ServicePointManager.Expect100Continue = false;
            //GetRequestToken();
            //Authorization();
            //GetAccessToken();
        }

        public void Emit(EmitData data)
        {
            ServicePointManager.Expect100Continue = false;

            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string normalizeUrl;
            string normalizedRequestParameters;

            string sig = oAuth.GenerateSignature(RECOMMENDATON_Uri, APIKEY, APIKEY_SECRET, accessToken, accessTokenSecret,
                "POST", timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizeUrl, out normalizedRequestParameters);
            sig = HttpUtility.UrlEncode(sig);

            //构造OAuth头部
            StringBuilder oauthHeader = new StringBuilder();
            oauthHeader.AppendFormat("OAuth realm=\"\", oauth_consumer_key={0}, ", APIKEY);
            oauthHeader.AppendFormat("oauth_nonce={0}, ", nonce);
            oauthHeader.AppendFormat("oauth_timestamp={0}, ", timeStamp);
            oauthHeader.AppendFormat("oauth_signature_method={0}, ", "HMAC-SHA1");
            oauthHeader.AppendFormat("oauth_version={0}, ", "1.0");
            oauthHeader.AppendFormat("oauth_signature={0}, ", sig);
            oauthHeader.AppendFormat("oauth_token={0}", accessToken);

            //构造请求
            StringBuilder atomData = new StringBuilder("<?xml version='1.0' encoding='UTF-8'?>");
            atomData.Append("<entry xmlns:ns0=\"http://www.w3.org/2005/Atom\"   xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:db=\"http://www.douban.com/xmlns/\">");
            atomData.AppendFormat("<title>{0}</title>", data.Title);
            atomData.AppendFormat("<db:attribute name=\"comment\">{0}</db:attribute>",data.Content);
            atomData.Append("<link href=\"http://api.douban.com/movie/subject/1424406\" rel=\"related\" />");
            atomData.Append("</entry>");

            Encoding encoding = Encoding.GetEncoding("utf-8");
            //string atomData = data.ToAtom10();
            byte[] bytes = encoding.GetBytes(atomData.ToString());

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(RECOMMENDATON_Uri);
            request.Headers.Set("Authorization", oauthHeader.ToString());
            request.ContentType = "application/atom+xml";
            request.Method = "POST";
            request.ContentLength = bytes.Length;
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(bytes, 0, bytes.Length);
            requestStream.Close();
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                StreamReader stream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
                string responseBody = stream.ReadToEnd();
                stream.Close();
                response.Close();
            }
            catch (WebException e)
            {
                string error = string.Empty;
                try
                {
                    StreamReader stream = new StreamReader(e.Response.GetResponseStream(), System.Text.Encoding.UTF8);
                    string responseBody = stream.ReadToEnd();
                    stream.Close();
                }
                catch { }

                throw new EmitException(error, e);
            }
        }

        public void GetRequestToken()
        {
            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string normalizeUrl, normalizedRequestParameters;

            string sig = oAuth.GenerateSignature(REQUEST_TOKEN_URL, APIKEY, APIKEY_SECRET, string.Empty, string.Empty,
                "GET",timeStamp,nonce,SignatureTypes.HMACSHA1,out normalizeUrl,out normalizedRequestParameters);
            sig = HttpUtility.UrlEncode(sig);

            StringBuilder sb = new StringBuilder(REQUEST_TOKEN_URL.ToString());
            sb.AppendFormat("?oauth_consumer_key={0}&", APIKEY);
            sb.AppendFormat("oauth_nonce={0}&", nonce);
            sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
            sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
            sb.AppendFormat("oauth_version={0}&", "1.0");
            sb.AppendFormat("oauth_signature={0}", sig);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(sb.ToString());
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader stream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
            string responseBody = stream.ReadToEnd();
            stream.Close();
            response.Close();

            Dictionary<string, string> responseValues = ParseResponse(responseBody);
            requestToken = responseValues["oauth_token"];
            requestTokenSecret = responseValues["oauth_token_secret"];
        }

        public void Authorization()
        {
            string url = AUTHORIZATION_URL + requestToken;
            //Uri accessuri = new Uri(url);
            //HttpWebRequest request = (HttpWebRequest)WebRequest.Create(accessuri);
            //HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            //StreamReader stream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
            //string responseBody = stream.ReadToEnd();
            //stream.Close();
            //response.Close();
        }

        public void GetAccessToken()
        {
            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string normalizeUrl, normalizedRequestParameters;

            string sig = oAuth.GenerateSignature(ACCESS_TOKEN_URL, APIKEY, APIKEY_SECRET, requestToken, requestTokenSecret, "GET", timeStamp,
                nonce,SignatureTypes.HMACSHA1,out normalizeUrl,out normalizedRequestParameters);
            sig = HttpUtility.UrlEncode(sig);

            StringBuilder sb = new StringBuilder(ACCESS_TOKEN_URL.ToString());
            sb.AppendFormat("?oauth_consumer_key={0}&", APIKEY);
            sb.AppendFormat("oauth_nonce={0}&", nonce);
            sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
            sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
            sb.AppendFormat("oauth_version={0}&", "1.0");
            sb.AppendFormat("oauth_signature={0}&", sig);
            sb.AppendFormat("oauth_token={0}&", requestToken);

            Uri accessuri = new Uri(sb.ToString());
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(accessuri);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader stream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
            string responseBody = stream.ReadToEnd();
            stream.Close();
            response.Close();

            Dictionary<string, string> responseValues = ParseResponse(responseBody);
            accessToken = responseValues["oauth_token"];
            accessTokenSecret = responseValues["oauth_token_secret"];
        }

        private Dictionary<string, string> ParseResponse(string parameters)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();

            if (!string.IsNullOrEmpty(parameters))
            {
                string[] p = parameters.Split('&');
                foreach (string s in p)
                    if (!string.IsNullOrEmpty(s))
                        if (s.IndexOf('=') > -1)
                        {
                            string[] temp = s.Split('=');
                            result.Add(temp[0], temp[1]);
                        }
                        else result.Add(s, string.Empty);
            }

            return result;
        }
    }
}
